package yuzhou;

import com.sun.jna.Memory;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.WinNT;

import java.util.ArrayList;
import java.util.List;

public class Mem {
    //取进程模块
    public static List<LPMODULEENTRY32> getModule(Integer pid){

        List<LPMODULEENTRY32> list = new ArrayList<>();

        Integer sp = Kernel32.INSTANCE.CreateToolhelp32Snapshot(8,pid);
        if(sp == 0)return list;

        byte[] info = LPMODULEENTRY32.getLPMODULEENTRY32();

        Integer hModule = Kernel32.INSTANCE.Module32First(sp,info);

        while (hModule!=0){
            LPMODULEENTRY32 lp = LPMODULEENTRY32.getInfo(info);
            list.add(lp);
            hModule = Kernel32.INSTANCE.Module32Next(sp,info);
        }

        Kernel32.INSTANCE.CloseHandle(hModule);
        return list;
    }

    public static Pointer readMem(Integer hProcess, Integer address){
        Pointer data = new Memory(4);
        Kernel32.INSTANCE.ReadProcessMemory(hProcess,address,data,4,0);
        return data;
    }
    public static Boolean writeMem(Integer hProcess,Integer address,Pointer data) {
        return Kernel32.INSTANCE.WriteProcessMemory(hProcess,address,data,4,0);
    }
    public static Boolean writeMemBool(Integer hProcess,Integer address,Pointer data) {
        return Kernel32.INSTANCE.WriteProcessMemory(hProcess,address,data,1,0);
    }
    public static List<Integer> findMem(Integer hProcess,Integer address,Integer qureyLen,String hex){
        return findMem(hProcess,address,qureyLen,hex,false);
    }

    public static List<Integer> findMem(Integer hProcess,Integer address,Integer qureyLen,String hex,Boolean isAll){
        List<Integer> list = new ArrayList<>();
        String arr[] = hex.split("\\s");

        WinNT.MEMORY_BASIC_INFORMATION lpBuffer = new WinNT.MEMORY_BASIC_INFORMATION();

        while (Kernel32.INSTANCE.VirtualQueryEx(hProcess,address,lpBuffer,28)!=0){
            if(lpBuffer.protect.intValue() != 16&&lpBuffer.protect.intValue()!=1&&lpBuffer.protect.intValue()!=512){
                Pointer data = new Memory(lpBuffer.regionSize.intValue());
                Kernel32.INSTANCE.ReadProcessMemory(hProcess,address,data,lpBuffer.regionSize.intValue(),0);

                for (int i=0;i<lpBuffer.regionSize.intValue();i++) {//i++
                    int finding = 0;
                    for (int n=0;n<arr.length;n++) {
                        if(i+n>=lpBuffer.regionSize.intValue())break;

                        if ("??".equals(arr[n])||data.getByte(i+n) == (byte)Integer.parseInt(arr[n], 16)){
                            finding++;
                        }

                    }
                    if(finding== arr.length){
                        list.add(address+i);
                        if(!isAll)break;
                    }
                }

                //System.out.println( data.dump(0,lpBuffer.regionSize.intValue()));
            }
            if (address>qureyLen)break;
            address += lpBuffer.regionSize.intValue();
        }
        return list;
    }
}
